文章目录
  1. Spark ALS
    1. 1. 简介
    2. 2. Spark ALS使用
    3. 3. ALS算法
      1. 3.1 获取损失函数
      2. 3.2 公式推导
    4. 4. 总结
    5. 参考

Spark ALS

1. 简介

推荐的意义和应用于推荐的协同过滤算法,这里就不说明了。这里主要讲解一下Spark对协同过滤的应用和实现。
官方文档 说的很明确,Spark目前支持的是基于模型的协同过滤算法,即Alternating Least Squares (ALS)。中文名称是交替最小二乘或者交替最小平方
由于该算法针对的是基于用户-商品的关联矩阵,且在实际应用中,一个用户不可能买过所有的商品,甚至也不可能对已经买过的所有商品进行评分,所以这个矩阵注定就是一个稀疏矩阵。假设我们已经有了用户数据商品数据评分数据,那么这个矩阵可能是这个样子(横轴是商品,众轴是用户,每个单元格式评分):

那么如何计算(预测)剩余?中的空值,那么这就是ALS做的事情了。

从这个算法,你也应该可以看出,它压根就不关心用户和商品本身的信息,需要的仅仅是用户对商品产生的某种行为,比如评分,浏览等等。

2. Spark ALS使用

在讲解ALS之前,我们先来看看在Spark中是如何使用的。这里采用Spark1.6.x的版本。虽然Spark ML中分为mlmllib两个版本的API,但就对于算法本身,影响不是很大。

实际应用中,应该会有离线推荐在线推荐两个场景。但不管是哪个场景,也仅仅是如何读取评分数据的区别,调用ALS的API都是一致的。

离线场景

对于离线场景,你可以将数据整理到Hive中,这个hive表中有user_id, item_id, rating这个三个字段。然后在spark应用程序中,你就可以通过Spark SQL来读取这些数据。然后使用val model = ALS.train(...)来训练这些数据,最后使用model就可以为用户推荐商品。然后还可以将推荐的结果数据存储在HBase数据库中以方便查询。

  • 注:当然还有ALS.trainImplicit(...)方法,这个是做隐式推荐的,默认是显式推荐。隐式的就是用户没有对商品有明确的评分行为,比如仅仅是点击或浏览。

在线场景

对于在线场景,你可能是在Spark Streaming中不停的接收来自Kafka的评分数据,然后结合历史数据进行推荐。操作基本和上述一致。

问题

这个 ALS.train(...) 的过程是神特么简单,真不愧是黑盒操作。。算法的细节简直完全对使用者屏蔽。对于这种demo,其实网上也是一堆,比如RecommendationExample,使用起来很是简单。
但是在使用的过程中,你可能会对传入的ranklambda等参数很是困惑,当然spark也很贴心的为你准备了默认值。或者你也可以结合实际数据来不停的调整它们,以达到最优的效果。那么这些参数在ALS中到底是起什么作用呢,那么就不得不去看下ALS算法的原理了。

3. ALS算法

3.1 获取损失函数

我看别人博客讲ALS简直一头雾水,终于借助哥们帮助下,终于能够理解了不少。那么下面我以菜鸟的眼光来讲解一下。

对于上面的稀疏矩阵,我们假设它为 A 矩阵,这是一个已知矩阵。假设有 i个用户j个商品,那么这个矩阵就是 i×j 的矩阵。

然后对于矩阵分解,其实任何一个矩阵 A(i×j) 都可以被分解成 U(i×k)V(j×k),即 (T表示V的转置矩阵,且k <= i,j)。比如一个4*4的矩阵,你可以将它分解成4*3矩阵3*4矩阵相乘的结果。这里的k,你可以把它当作是一个特征参数,对应Spark ALS中就是rank参数。

但是在这个打分矩阵中,找到完全吻合的U和V是不可能的,所以需要找到一个近似的解。即k <= i,j

此时你就会发现,我们的目的实际就是去求 UV两个矩阵的解。但是直接去求结果肯定不可能,那么我的理解就是先从预测结果的好坏程度出发。

我们假设有如下公式:

这时你应该会发现如果我们求得的U和V如果越优,那么C的值越小。而且这个公式在实际中肯定会存在一个最小值(只是求不到),此时我们的方向就是去求这个公式的最小值。

但是这个公式有个明显的缺点,就是过于拟合。说白了就是,我这个公式在训练集中能满足大部分数据,但是在测试集中就会存在很多偏离这个函数公式的数据,这就会导致很多指标有很大的误差,如图(右图表示过于拟合):

那么怎么才能达到左图的效果,使得结果的指标没有很大的误差。那么就需要对上述的公式进行惩罚,公式变成如下(损失函数)。

至于为毛加了后面那串公式,可以参照矩阵分解中的 正则化矩阵分解。原理我也不是很懂,反正就是解决过拟合的问题。其中的λ(lambda)也是Spark ALS的设置项。

那么对于损失函数(Loss Function)的优化,通常可以采用交替最小二乘法(Alternative Least Squares)随机梯度下降法(Stochastic Gradient Descent)。下面就开始介绍是如何通过 ALS 对这个函数进行不断的优化,从而求得以C是最小值的前提下,这个U和V的最优解。

由于公式里面存在两个变量U和V,所以肯定需要固定一个变量(假设其为常数),这样才能求最小值下的另一个变量的值。步骤如下:

3.2 公式推导

第一步:

首先我们假设U的值是个常量,即U(0)。这个值你可以随机生成,取0或者取全局的均值。那么求最小值,就需要对这个公式的V进行求导

然后令导函数的值为0。从而求到最小值下的V(0),可以参照推导步骤

这样经过第一步,就可以得到一个V的解,即V(0)

第二步

既然已经求到了 V(0),那么我们就可以把V的值设成常量V(0),从而去求U(1)。这个求值的过程就跟第一步差不多了。

第N步

…… 按照上述的思路一次次迭代,这个过程就是求U和V最优解的交替过程。迭代的次数可以人为指定,这也是Spark ALS中的设置参数。

这样损失函数C的值就会不断的收敛,这样就会求出一个近似最优的解U和V。

4. 总结

至此,经过不停的交替求C的最小值的过程,从而求得最优的U和V的解。这也是ALS名称的由来。这样在去计算 U*V 的值,就可以将原先稀疏的矩阵A中的空缺值补充完毕,这是一个预测的过程。

然后就可以通过这个预测后的矩阵对每个用户进行商品的推荐了,比如可以按照分值从大到小推荐出前10个商品出来。

参考

基于Spark机器学习和实时流计算的智能推荐系统
矩阵分解原理详解
推荐demo
隐式反馈推荐

文章目录
  1. Spark ALS
    1. 1. 简介
    2. 2. Spark ALS使用
    3. 3. ALS算法
      1. 3.1 获取损失函数
      2. 3.2 公式推导
    4. 4. 总结
    5. 参考